<template>
  <div class="workflow-editor">
    <div class="editor-header">
      <span class="title">{{ currentTab.name }}</span>
      <div class="btns">
        <el-button size="mini" @click="excuDateDialog = true">运行</el-button>
        <el-button size="mini" @click="backfillDialog = true">Backfill 运行</el-button>
        <el-button size="mini" @click="saveWorkflow">保存</el-button>
        <el-button size="mini" type="primary" @click="drawer = true">配置</el-button>
      </div>
    </div>
    <div class="editor-content">
      <div class="workflow-cavans">
        <flow
          v-if="showFlow"
          v-model="flowData"
          :nodes="nodeCategory"
          @click="nodeClick"
          @edit-task="editTask"
        ></flow>
      </div>
    </div>
    <el-drawer
      :visible.sync="drawer"
      :with-header="false"
      append-to-body
      title="工作流调度配置"
      size="40%"
    >
      <workflow-setting v-if="drawer" :id="currentTab.id" :flow-data="flowData"></workflow-setting>
    </el-drawer>

    <!-- 设置关联 task -->
    <el-drawer
      :visible.sync="referenceTaskVisible"
      :before-close="beforeCloseReferenceTask"
      :with-header="false"
      append-to-body
      title="关联任务"
      size="40%"
      @opened="referenceTaskOpen"
    >
      <div class="setting-wrapper">
        <div class="setting-right">
          <el-card>
            <div slot="header" class="clearfix">
              <span style="font-size: 16px">关联任务</span>
              <el-button
                style="float: right; padding: 3px 0"
                type="text"
                @click="referenceTaskVisible = false"
                >关闭</el-button
              >
            </div>
            <el-form label-width="120px">
              <el-form-item
                v-if="currentNode.type != 'START' && currentNode.type != 'END'"
                label="关联任务"
              >
                <el-select
                  v-model="referenceTaskid"
                  placeholder="请选择任务"
                  clearable
                  filterable
                  @change="setReferenceTask"
                >
                  <el-option
                    v-for="item in taskOptions"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  >
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="关联子节点">
                <el-select
                  v-model="referenceTaskids"
                  multiple
                  filterable
                  collapse-tags
                  placeholder="请选择关联子节点"
                  @change="setReferenceNode"
                >
                  <el-option
                    v-for="item in filterNodes"
                    :key="item.stateId"
                    :label="item.name"
                    :value="item.stateId"
                  >
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </el-card>
        </div>
      </div>
    </el-drawer>

    <el-dialog :visible.sync="excuDateDialog" title="选择计划时间" width="30%">
      <el-form>
        <el-form-item label="计划时间" required>
          <el-date-picker
            v-model="execution_date"
            type="datetime"
            placeholder="选择日期"
            style="width: 100%"
          >
          </el-date-picker>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="excuDateDialog = false">取 消</el-button>
        <el-button type="primary" @click="runWorkflow">确 定</el-button>
      </div>
    </el-dialog>

    <el-dialog :visible.sync="backfillDialog" title="Backfill 运行" width="30%">
      <el-form>
        <el-form-item label="开始时间" required>
          <el-date-picker
            v-model="startTime"
            type="datetime"
            placeholder="选择日期"
            style="width: 100%"
          >
          </el-date-picker>
        </el-form-item>
        <el-form-item label="结束时间" required>
          <el-date-picker
            v-model="endTime"
            type="datetime"
            placeholder="选择日期"
            style="width: 100%"
          >
          </el-date-picker
        ></el-form-item>
        <el-form-item label="顺序执行" required>
          <el-switch v-model="is_synchronous"></el-switch>
        </el-form-item>
        <el-form-item label="任务数" v-if="is_synchronous">
           <el-input-number v-model="synchronous_num" :min="1"></el-input-number>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="backfillDialog = false">取 消</el-button>
        <el-button type="primary" @click="runBackfill">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
import WorkflowSetting from "./workflow-setting";
import { Flow } from "VIEW/components";
import { Layout } from "VIEW/components/flow/util.js";
export default {
  name: "WorkflowEditor",
  components: {
    WorkflowSetting,
    Flow
  },
  data() {
    return {
      showFlow: true,
      excuDateDialog: false,
      backfillDialog: false,
      execution_date: "",
      startTime: "",
      endTime: "",
      is_synchronous: false,
      synchronous_num: 1,
      referenceTaskids: [],
      referenceTaskid: "",
      referenceTaskVisible: false,
      drawer: false,
      flowData: [],
      nodeCategory: [
        {
          groupName: "控制节点",
          groupId: "1",
          data: [
            {
              nodeId: "1",
              type: "START",
              name: "Start"
            },
            {
              nodeId: "2",
              type: "END",
              name: "End"
            }
          ]
        },
        {
          groupId: "2",
          groupName: "作业节点",
          data: []
        }
      ],
      taskOptions: [],
      currentNode: {},
      filterNodes: []
    };
  },
  computed: {
    ...mapState({
      currentTab: ({ data }) => data.currentTab
    })
  },
  watch: {
    ["currentTab.id"]: {
      handler(id) {
        // 直接修改 flowdata 在 tab 切换时候会有连线不显示 bug（应该是 flow 组件内部对 数据变化没有及时响应，通过 v-if 对组件进行重新 render 解决）
        this.showFlow = false;
        let flowData = [];
        if (
          this.currentTab.content &&
          this.currentTab.content.nodes &&
          this.currentTab.content.nodes.length
        ) {
          flowData = JSON.parse(JSON.stringify(this.currentTab.content.nodes));
        }
        this.$nextTick(() => {
          this.flowData = flowData;
          this.showFlow = true;
        });
      },
      immediate: true
    }
  },
  mounted() {
    this.initData();
  },
  methods: {
    ...mapMutations(["updataTabContent", "setCurrentTab"]),
    setReferenceTask() {
      if (this.referenceTaskid) {
        this.$set(this.currentNode, "taskId", this.referenceTaskid);
        this.currentNode.name = this.taskOptions.find(
          task => task.id === this.referenceTaskid
        ).name;
      } else {
        this.currentNode.taskId = "";
        this.currentNode.name = "";
      }
    },
    setReferenceNode() {
      if (this.referenceTaskids.length > 0) {
        let endNode = this.filterNodes[this.filterNodes.length - 1];
        this.currentNode.branches = this.referenceTaskids.map((node, index) => {
          if (endNode.stateId === node) {
            return {
              nextStateId: node,
              branchId: index + 1,
              nextStateType: "end"
            };
          } else {
            return {
              nextStateId: node,
              branchId: index + 1
            };
          }
        });
      } else {
        this.currentNode.branches = [];
      }
    },
    // 节点被点击
    nodeClick(data) {
      if (data.type === "END") return;
      this.currentNode = data;
      this.referenceTaskVisible = true;
    },
    editTask(data) {
      Promise.all([
        this.$http.task.getTaskById({ id: data.taskId }),
        this.$http.task.getTaskLastInstance({ id: data.taskId })
      ]).then(res => {
        let result = { ...res[0], ...res[1], menuType: 0 };
        this.setCurrentTab(result);
      });
    },
    referenceTaskOpen() {
      let project_id = this.currentTab.project_id;
      let operator = this.currentNode.type;
      this.$http.workflow.getReferenceTasks({ project_id, operator }).then(res => {
        this.taskOptions = res;
        this.referenceTaskid = this.currentNode.taskId || "";
      });
      this.filterNodes = this.flowData.filter(node => {
        return node.stateId !== this.currentNode.stateId;
      });
      this.referenceTaskid = this.currentNode.taskId || "";
      this.referenceTaskids = this.currentNode.branches.map(branch => branch.nextStateId) || [];
    },
    beforeCloseReferenceTask(done) {
      this.taskOptions = [];
      this.referenceTaskid = "";
      this.referenceTaskids = [];
      done();
    },
    initData() {
      this.$http.task.getTaskTypes().then(res => {
        this.nodeCategory[1].data = res.map((item, index) => {
          return {
            nodeId: index + 1,
            type: item.value,
            name: item.label
          };
        });
      });
    },
    runWorkflow() {
      let { execution_date } = this;
      this.$http.workflow
        .runWorkflow({ id: this.currentTab.id, execution_date: +new Date(execution_date) })
        .then(res => {
          this.excuDateDialog = false;
          this.$message({
            type: "success",
            message: "运行成功"
          });
          this.$bus.$emit("refresh-workflow-history");
        });
    },

    runBackfill() {
      let { startTime, endTime, is_synchronous, synchronous_num } = this;
      this.$http.workflow
        .runBackfill({
          id: this.currentTab.id,
          start_date: +new Date(startTime),
          end_date: +new Date(endTime),
          is_synchronous,
          synchronous_num
        })
        .then(res => {
          this.startTime = this.endTime = "";
          this.backfillDialog = false;
          this.$message({
            type: "success",
            message: "backfill 运行成功"
          });
          this.$bus.$emit("refresh-workflow-backfill");
        });
    },

    saveWorkflow() {
      let { id } = this.currentTab;
      let content = {
        nodes: this.flowData
      };
      this.$http.workflow.updateWorkflow({ id, content }).then(res => {
        this.$message({
          type: "success",
          message: "保存成功"
        });
        // 同步全局变量
        let curContent = {
          ...this.currentTab,
          content
        };
        this.setCurrentTab(curContent)
      });
    }
    // autoLayout() {
    //   const layout = new Layout(this.flowData);
    //   layout.autoLayout();
    // }
  }
};
</script>
<style lang="scss">
.workflow-editor {
  height: 50%;
  flex: 1;
  position: relative;
  .editor-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid #e4e7ed;
    padding: 8px 8px;
  }
  .editor-content {
    height: calc(100% - 40px);
    overflow: hidden;
    position: relative;
    .workflow-cavans {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }
    .CodeMirror {
      height: 100%;
    }
  }
}
.setting-wrapper {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: hidden;
  display: flex;
  .setting-right {
    flex: 1;
    & > .el-card {
      border: none;
      box-shadow: none;
    }
    .el-card__header {
      padding: 16px 20px;
    }
  }
  .el-menu {
    height: 100%;
  }
}
.referen-children {
  display: flex;
  justify-content: center;
}
</style>
